package com.codeyang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codeyang.constans.Constants;
import com.codeyang.domain.Role;
import com.codeyang.domain.RoleMenu;
import com.codeyang.domain.RoleUser;
import com.codeyang.dto.RoleDto;
import com.codeyang.mapper.RoleMapper;
import com.codeyang.mapper.RoleMenuMapper;
import com.codeyang.mapper.RoleUserMapper;
import com.codeyang.service.RoleService;
import com.codeyang.utils.DataSplitUtil;
import com.codeyang.vo.DataGridView;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 描述: TO-删除标志-DO
 *
 * @author CodeYang_Site
 * @version 2021/4/20 15:34
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public DataGridView lisPage(RoleDto roleDto) {
        Page<Role> page = new Page<>(roleDto.getPageNum(), roleDto.getPageSize());
        QueryWrapper<Role> qw = new QueryWrapper<>();
        // 排序
        page.addOrder(OrderItem.desc(Role.COL_UPDATE_TIME));
        // 角色name code status 时间
        qw.like(StringUtils.isNotBlank(roleDto.getRoleName()), Role.COL_ROLE_NAME, roleDto.getRoleName());
        qw.eq(StringUtils.isNotBlank(roleDto.getRoleCode()), Role.COL_ROLE_CODE, roleDto.getRoleCode());
        qw.eq(StringUtils.isNotBlank(roleDto.getStatus()), Role.COL_STATUS, roleDto.getStatus());
        qw.between(
                roleDto.getBeginTime() != null && roleDto.getEndTime() != null,
                Role.COL_CREATE_TIME,
                roleDto.getBeginTime(),
                roleDto.getEndTime()
        );
        roleMapper.selectPage(page, qw);
        return new DataGridView(page.getTotal(), page.getRecords());
    }

    @Override
    public boolean saveRole(RoleDto roleDto) {
        Role role = new Role();
        BeanUtils.copyProperties(roleDto, role);
        // data person
        role.setCreateTime(new Date());
        role.setCreateBy(roleDto.getSimpleUser().getUserName());
        role.setUpdateTime(role.getCreateTime());
        return roleMapper.insert(role) > 0;
    }

    @Override
    public boolean updateRole(RoleDto roleDto) {
        Role role = new Role();
        BeanUtils.copyProperties(roleDto, role);
        role.setUpdateTime(new Date());
        role.setUpdateBy(roleDto.getSimpleUser().getUserName());
        return roleMapper.updateById(role) > 0;
    }

    @Override
    public List<Role> selectAllRole() {
        QueryWrapper<Role> qw = new QueryWrapper<>();
        // 状态
        qw.eq(Role.COL_STATUS, Constants.STATUS_TRUE);
        // 排序
        qw.orderByAsc(Role.COL_ROLE_SORT);
        return roleMapper.selectList(qw);
    }

    @Override
    public List<Long> getRoleIdsByUserId(Long userId) {
        /**
         * 查询中间表
         * user---role  -===userRole
         */
        QueryWrapper<RoleUser> qw = new QueryWrapper<>();
        qw.eq(RoleUser.COL_USER_ID, userId);

        List<RoleUser> roleUsers = roleUserMapper.selectList(qw);
        if (CollectionUtils.isEmpty(roleUsers)) {
            return Collections.emptyList();
        }
        //不为空 收集一下 根据角色id收集
        // lomdb最终会变成一个for循环
        // 角色id
        List<Long> collect = roleUsers.parallelStream().map(RoleUser::getRoleId).collect(Collectors.toList());
        return collect;
    }


    /**
     * 保存中间表的数据
     *
     * @param userId
     * @param roleIds
     */
    @Transactional
    @Override
    public void saveRoleUser(Long userId, Long[] roleIds) {
        if (roleIds == null || roleIds.length == 0 || roleIds[0] == -1) {
            return;
        }
        //删除旧数据 - 根据用户id删除
        QueryWrapper<RoleUser> qw = new QueryWrapper<>();
        qw.eq(RoleUser.COL_USER_ID, userId);
        roleUserMapper.delete(qw);
        //新增新数据
        //循环因为一个用户可能有多个角色
        //做一下sql 批量的记录
        List<RoleUser> roleUsers = new ArrayList<>(roleIds.length);
        for (Long roleId : roleIds) {
            RoleUser roleUser = new RoleUser();
            roleUser.setUserId(userId);
            roleUser.setRoleId(roleId);
            roleUsers.add(roleUser);
            //尽量避免在循环里做sql操作 多次sql 涉及io 慢
        }
        //        roleUserMapper.insert();
        // roleUsers 新增这个集合
        // 1批量新增 一次太长也会造成性能降低  scoket 连接 mysql执行 都会有影响
        // 2所以做一个 分页批量 取一个中间量 增强性能
        // 3分割数据 按同类型分割数据
        // 每次按20条分割
        List<List<RoleUser>> batchDatas = DataSplitUtil.splitList(roleUsers, 20);
        int totalAddRows = 0;
        for (List<RoleUser> batchData : batchDatas) {
            totalAddRows += roleUserMapper.bathInser(batchData);
        }


    }



    /**
     * 保存角色-菜单关系
     * 多个写操作+事务
     * 事务原理:
     * comit(flase)
     * exec(sql1)
     * exec(sql2)
     * commit/rollback
     *
     * @param roleId
     * @param menuIds
     */
    @Transactional
    @Override
    public void saveRoleMenu(Long roleId, Long[] menuIds) {

        if (menuIds == null || menuIds.length == 0 || menuIds[0] == -1) {
            return;
        }
        // 1 删除旧的数据
        QueryWrapper<RoleMenu> qw = new QueryWrapper<>();
        qw.eq(RoleMenu.COL_ROLE_ID, roleId);
        roleMenuMapper.delete(qw);
        // 2 新增新的数据
        List<RoleMenu> roleMenus = new ArrayList<>(menuIds.length);

        for (Long menuId : menuIds) {
            // 角色菜单关系 添加
            roleMenus.add(new RoleMenu(roleId, menuId));
        }
        // 批量切割
        List<List<RoleMenu>> lists = DataSplitUtil.splitList(roleMenus, 20);
        int rows = 0;
        for (List<RoleMenu> batchData : lists) {
            rows += roleMenuMapper.batchInsert(batchData);
        }

        System.out.println("本次新增数据为row" + rows);

    }


    /**
     * 测试截取数据
     *
     * @param args
     */
    public static void main(String[] args) {

        int totalSize = 100;
        List<Integer> allData = new ArrayList<>();
        int i = 0;
        while (i < 100) {
            allData.add(i + 1);
            i++;
        }
        List<List<Integer>> lists = DataSplitUtil.splitList(allData, 20);
        System.out.println(lists);

    }

    @Override
    public List<String> getUserRolesCode(Long userId) {


        return roleMenuMapper.getUserRolesCode(userId);
    }
}
